home *** CD-ROM | disk | FTP | other *** search
/ Tech Win 1999 February / TECH Win 02-1999 Disc A.iso / ols / lzh / tcl211.lzh / DLLSRC.lzh / wndproc.c < prev   
Encoding:
C/C++ Source or Header  |  1998-10-27  |  17.1 KB  |  702 lines

  1. /*-----------------------------------------------------
  2.   wndproc.c
  3.     時計の改造
  4.                                     KAZUBON 1997-1998
  5. -------------------------------------------------------*/
  6.  
  7. #include "tcdll.h"
  8.  
  9. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  10. void InitClock(HWND hwnd);
  11. void EndClock(void);
  12. BOOL IsIE4(HWND hwnd);
  13. HMENU CreateClockMenu(void);
  14. void CreateTip(HWND hwnd);
  15. void CreateClockDC(HWND hwnd);
  16. void ReadData(HWND hwnd);
  17. void OnTimer(HWND hwnd);
  18. void DrawClockSub(HWND hwnd, HDC hdc, SYSTEMTIME* pt);
  19. void DrawClock(HWND hwnd, HDC hdc);
  20. LRESULT OnCalcRect(HWND hwnd);
  21. void OnTooltipNeedText(UINT code, LPARAM lParam);
  22.  
  23. /*------------------------------------------------
  24.  各プロセスで共通のデータ
  25. --------------------------------------------------*/
  26. #pragma data_seg(".MYDATA")
  27. HHOOK hhook = 0;
  28. HWND hwndTClockMain = NULL;
  29. HWND hwndClock = NULL;
  30. #pragma data_seg()
  31.  
  32. /*------------------------------------------------
  33.  Globals
  34. --------------------------------------------------*/
  35. HANDLE hmod = 0;
  36. WNDPROC oldWndProc = NULL;
  37. HDC hdcClock = NULL;
  38. HBITMAP hbmpClock = NULL;
  39. HFONT hFon = NULL;
  40. HMENU hMenu = NULL;
  41. HWND hwndTip = NULL;
  42. COLORREF colback, colfore;
  43. char format[1024];
  44. BOOL bHour12, bHourZero;
  45. int hourLast = -1, minuteLast = -1;
  46. BOOL bNoClock = FALSE;
  47. int nBlink = 0;
  48. int buttondown = 0;
  49. BOOL bStartMenuClock = FALSE;
  50. BOOL bIE4 = FALSE;
  51. char tooltip[80];
  52. int dvpos = 0, dheight = 0;
  53.  
  54. extern HWND hwndStart;
  55. extern HWND hwndStartMenu;
  56.  
  57. /*------------------------------------------------
  58.  時計の初期化
  59. --------------------------------------------------*/
  60. void InitClock(HWND hwnd)
  61. {
  62.     BOOL b;
  63.  
  64.     hwndClock = hwnd;
  65.     
  66.     PostMessage(hwndTClockMain, WM_USER, 0, (LPARAM)hwnd);
  67.     
  68.     //レジストリ読み込み
  69.     ReadData(hwndClock);
  70.     //サブクラス化
  71.     oldWndProc = (WNDPROC)GetWindowLong(hwndClock, GWL_WNDPROC);
  72.     SetWindowLong(hwndClock, GWL_WNDPROC, (LONG)WndProc);
  73.     //ダブルクリック受け付ける
  74.     SetClassLong(hwndClock, GCL_STYLE,
  75.         GetClassLong(hwndClock, GCL_STYLE) | CS_DBLCLKS);
  76.     //スタートボタンの初期化
  77.     SetStartButton(hwndClock);
  78.     //スタートメニューの初期化
  79.     SetStartMenu(hwndClock);
  80.     
  81.     //1秒おきにタイマをかける
  82.     SetTimer(hwndClock, 1, 1000, NULL);
  83.     //ツールチップ作成
  84.     CreateTip(hwndClock);
  85.     
  86.     b = GetMyRegLong(NULL, "DropFiles", FALSE);
  87.     DragAcceptFiles(hwnd, b);
  88.     
  89.     bIE4 = IsIE4(hwndClock);
  90.     
  91.     if(bIE4) InitStartMenuIE4();
  92.     
  93.     //タスクバーの更新
  94.     PostMessage(GetParent(GetParent(hwndClock)), WM_SIZE,
  95.         SIZE_RESTORED, 0);
  96.     InvalidateRect(GetParent(GetParent(hwndClock)), NULL, TRUE);
  97. }
  98.  
  99. /*------------------------------------------------
  100.  時計の終了処理
  101. --------------------------------------------------*/
  102. void DeleteClockRes(void)
  103. {
  104.     if(hFon) DeleteObject(hFon); hFon = NULL;
  105.     if(hdcClock) DeleteDC(hdcClock); hdcClock = NULL;
  106.     if(hbmpClock) DeleteObject(hbmpClock); hbmpClock = NULL;
  107.     ClearTimer();
  108. }
  109. void EndClock(void)
  110. {
  111.     DragAcceptFiles(hwndClock, FALSE);
  112.     if(hwndTip) DestroyWindow(hwndTip); hwndTip = NULL;
  113.     EndStartButton();
  114.     EndStartMenu();
  115.     if(hMenu) DestroyMenu(hMenu); hMenu = NULL;
  116.     ClearStartMenuIE4();
  117.     
  118.     DeleteClockRes();
  119.     
  120.     if(hwndClock && IsWindow(hwndClock))
  121.     {
  122.         KillTimer(hwndClock, 1);
  123.         SetWindowLong(hwndClock, GWL_WNDPROC, (LONG)oldWndProc);
  124.         oldWndProc = NULL;
  125.     }
  126.     //TClockウィンドウを終了させる
  127.     if(IsWindow(hwndTClockMain))
  128.         PostMessage(hwndTClockMain, WM_USER+2, 0, 0);
  129. }
  130.  
  131. /*------------------------------------------------
  132.  IE4かどうか
  133. --------------------------------------------------*/
  134. BOOL IsIE4(HWND hwnd)
  135. {
  136.     char classname[80];
  137.  
  138.     hwnd = GetParent(GetParent(hwnd));
  139.     if(hwnd == NULL) return FALSE;
  140.     hwnd = GetWindow(hwnd, GW_CHILD);
  141.     while(hwnd)
  142.     {
  143.         GetClassName(hwnd, classname, 80);
  144.         if(lstrcmpi(classname, "ReBarWindow32") == 0)
  145.             return TRUE;
  146.         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  147.     }
  148.     return FALSE;
  149. }
  150.  
  151. /*------------------------------------------------
  152.  時計ウィンドウのサブクラスプロシージャ
  153. --------------------------------------------------*/
  154. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  155. {
  156.     switch(message) // ツールチップ対応
  157.     {
  158.         case WM_LBUTTONDOWN:
  159.         case WM_RBUTTONDOWN:
  160.         case WM_MBUTTONDOWN:
  161.         case WM_LBUTTONUP:
  162.         case WM_RBUTTONUP:
  163.         case WM_MBUTTONUP:
  164.         case WM_MOUSEMOVE:
  165.         {
  166.             MSG msg;
  167.             msg.hwnd = hwnd;
  168.             msg.message = message;
  169.             msg.wParam = wParam;
  170.             msg.lParam = lParam;
  171.             msg.time = GetMessageTime();
  172.             msg.pt.x = LOWORD(GetMessagePos());
  173.             msg.pt.y = HIWORD(GetMessagePos());
  174.             if(hwndTip)
  175.                 SendMessage(hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
  176.         }
  177.     }
  178.     
  179.     switch(message)
  180.     {
  181.         case WM_DESTROY:
  182.             DeleteClockRes();
  183.             break;
  184.         // 親ウィンドウから送られ、サイズを返すメッセージ
  185.         case (WM_USER+100):
  186.             if(bNoClock) break;
  187.             return OnCalcRect(hwnd);
  188.         // システムの設定を反映する
  189.         case WM_SYSCOLORCHANGE:
  190.             CreateClockDC(hwnd); //hdcClock作り直し
  191.         case WM_WININICHANGE:
  192.         case WM_TIMECHANGE:
  193.         // 親ウィンドウから送られる
  194.         case (WM_USER+101):
  195.         {
  196.             HDC hdc;
  197.             if(bNoClock) break;
  198.             hdc = GetDC(hwnd);
  199.             DrawClock(hwnd, hdc);
  200.             ReleaseDC(hwnd, hdc);
  201.             return 0;
  202.         }
  203.         case WM_SIZE:
  204.             CreateClockDC(hwnd); //hdcClock作り直し
  205.             break;
  206.         case WM_ERASEBKGND:
  207.             break;
  208.         case WM_PAINT:
  209.         {
  210.             PAINTSTRUCT ps;
  211.             HDC hdc;
  212.             if(bNoClock) break;
  213.             hdc = BeginPaint(hwnd, &ps);
  214.             DrawClock(hwnd, hdc);
  215.             EndPaint(hwnd, &ps);
  216.             return 0;
  217.         }
  218.         case WM_TIMER:
  219.             if(wParam == 1)
  220.             {
  221.                 OnTimer(hwnd); return 0;
  222.             }
  223.             else
  224.             {
  225.                 if(bNoClock) break;
  226.                 else return 0;
  227.             }
  228.         // マウスダウン
  229.         case WM_LBUTTONDOWN:
  230.         case WM_RBUTTONDOWN:
  231.         case WM_MBUTTONDOWN:
  232.             if(nBlink)
  233.             {
  234.                 nBlink = 0; InvalidateRect(hwnd, NULL, TRUE);
  235.             }
  236.             if(message == WM_LBUTTONDOWN && bStartMenuClock &&
  237.                 hwndStart && IsWindow(hwndStart))
  238.             {
  239.                 SetWindowPos(hwndStart, NULL, 0, 0, 0, 0,
  240.                     SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  241.                 // スタートメニュー
  242.                 PostMessage(hwndStart, WM_LBUTTONDOWN, 0, 0);
  243.             }
  244.             buttondown = message;
  245.             return 0;
  246.         // マウスアップ
  247.         case WM_LBUTTONUP:
  248.             if(buttondown == WM_LBUTTONDOWN)
  249.                 PostMessage(hwndTClockMain, buttondown, wParam, lParam);
  250.             buttondown = 0;
  251.             return 0;
  252.         case WM_RBUTTONUP:
  253.             if(buttondown == WM_RBUTTONDOWN)
  254.                 PostMessage(hwndTClockMain, buttondown, wParam, lParam);
  255.             buttondown = 0;
  256.             break;
  257.         case WM_MBUTTONUP:
  258.             if(buttondown == WM_MBUTTONDOWN)
  259.                 PostMessage(hwndTClockMain, buttondown, wParam, lParam);
  260.             buttondown = 0;
  261.             return 0;
  262.         // ダブルクリック
  263.         case WM_LBUTTONDBLCLK:
  264.             if(bStartMenuClock) return 0;
  265.         case WM_RBUTTONDBLCLK:
  266.         case WM_MBUTTONDBLCLK:
  267.             PostMessage(hwndTClockMain, message, wParam, lParam);
  268.             return 0;
  269.         case WM_MOUSEMOVE:
  270.             return 0;
  271.         case WM_CONTEXTMENU:   // 右クリックメニュー
  272.             if(!hMenu)
  273.                 hMenu = CreateClockMenu();
  274.             SetTimerMenu(hMenu);
  275.             TrackPopupMenu(hMenu, TPM_LEFTALIGN,
  276.                 LOWORD(lParam), HIWORD(lParam), 0, hwnd, NULL);
  277.             return 0;
  278.         case WM_NCHITTEST: // oldWndProcに処理させない
  279.             return DefWindowProc(hwnd, message, wParam, lParam);
  280.         case WM_MOUSEACTIVATE:
  281.             return MA_ACTIVATE;
  282.         // ファイルのドロップ
  283.         case WM_DROPFILES:
  284.             PostMessage(hwndTClockMain, WM_DROPFILES, wParam, lParam);
  285.             return 0;
  286.         case WM_COMMAND:
  287.         {
  288.             WORD wID;
  289.             wID = LOWORD(wParam);
  290.             switch (wID)
  291.             {
  292.                 case 100: // TClockのプロパティ
  293.                     PostMessage(hwndTClockMain, WM_USER+1, 0, 0);
  294.                     return 0;
  295.                 case 101: // TClockのヘルプ
  296.                     PostMessage(hwndTClockMain, WM_USER+5, 0, 0);
  297.                     return 0;
  298.                 case 102: // TClockの終了
  299.                     EndClock();
  300.                     return 0;
  301.                 case 103: // タイマー
  302.                     PostMessage(hwndTClockMain, WM_USER+6, (WPARAM)hwnd, 0);
  303.                     return 0;
  304.                 case 408:
  305.                 case 403:
  306.                 case 404:
  307.                 case 405:
  308.                 case 415:
  309.                 case 420:
  310.                 case 413:
  311.                     PostMessage(GetParent(GetParent(hwnd)), message,
  312.                         wParam, lParam);
  313.                     return 0;
  314.             }
  315.             if(wID >= 110)
  316.             {
  317.                 StopTimer(wID - 110); return 0;
  318.             }
  319.             break;
  320.         }
  321.         case WM_NOTIFY: //ツールチップのテキスト表示
  322.         {
  323.             UINT code;
  324.             code = ((LPNMHDR)lParam)->code;
  325.             if(code == TTN_NEEDTEXT || code == TTN_NEEDTEXTW)
  326.             {
  327.                 OnTooltipNeedText(code, lParam);
  328.                 return 0;
  329.             }
  330.             break;
  331.         }
  332.         case (WM_USER+1): // RefreshTClock() から送られる
  333.         {
  334.             BOOL b;
  335.             ReadData(hwnd);
  336.             SetStartButton(hwnd);
  337.             SetStartMenu(hwnd);
  338.             CreateClockDC(hwnd);
  339.             b = GetMyRegLong(NULL, "DropFiles", FALSE);
  340.             DragAcceptFiles(hwnd, b);
  341.             InvalidateRect(hwnd, NULL, FALSE);
  342.             PostMessage(GetParent(GetParent(hwnd)), WM_SIZE,
  343.                 SIZE_RESTORED, 0);
  344.             InvalidateRect(GetParent(GetParent(hwndClock)), NULL, TRUE);
  345.             return 0;
  346.         }
  347.         case (WM_USER+2): // BlinkTClock() から送られる
  348.         {
  349.             if(wParam) { if(nBlink == 0) nBlink = 4; }
  350.             else nBlink = 2;
  351.             return 0;
  352.         }
  353.         
  354.         case (WM_USER+6): // タイマー開始
  355.             StartTimer(lParam);
  356.             return 0;
  357.  
  358.         case WM_WINDOWPOSCHANGING:  // サイズ調整
  359.         {
  360.             LPWINDOWPOS pwp;
  361.             if(bNoClock) break;
  362.             pwp = (LPWINDOWPOS)lParam;
  363.             if(IsWindowVisible(hwnd) && !(pwp->flags & SWP_NOSIZE))
  364.             {
  365.                 int h;
  366.                 h = (int)HIWORD(OnCalcRect(hwnd));
  367.                 if(pwp->cy > h) pwp->cy = h;
  368.             }
  369.             break;
  370.         }
  371.     }
  372.     /*
  373.     {
  374.         char s[80];
  375.         wsprintf(s, "%X", message);
  376.         WriteDebug(s);
  377.     }
  378.     */
  379.     return CallWindowProc(oldWndProc, hwnd, message, wParam, lParam);
  380. }
  381.  
  382. /*------------------------------------------------
  383.  設定の読み込みとデータの初期化
  384. --------------------------------------------------*/
  385. void ReadData(HWND hwnd)
  386. {
  387.     char s[1024];
  388.     char fontname[1024];
  389.     int fontsize;
  390.     LONG weight, italic;
  391.  
  392.     colfore = GetMyRegLong(NULL, "ForeColor", 
  393.         0x80000000 | COLOR_BTNTEXT);
  394.     colback = GetMyRegLong(NULL, "BackColor",
  395.         0x80000000 | COLOR_3DFACE);
  396.     
  397.     GetMyRegStr(NULL, "Font", fontname, "");
  398.     
  399.     fontsize = GetMyRegLong(NULL, "FontSize", 9);
  400.     weight = GetMyRegLong(NULL, "Bold", 0);
  401.     if(weight) weight = FW_BOLD;
  402.     else weight = FW_NORMAL;
  403.     italic = GetMyRegLong(NULL, "Italic", 0);
  404.     
  405.     if(hFon) DeleteObject(hFon);
  406.     hFon = CreateMyFont(fontname, fontsize, weight, italic);
  407.     
  408.     dvpos = (int)(short)GetMyRegLong(NULL, "VertPos", 0);
  409.     dheight = (int)(short)GetMyRegLong(NULL, "ClockHeight", 0);
  410.     
  411.     bNoClock = GetMyRegLong(NULL, "NoClock", FALSE);
  412.     
  413.     if(!GetMyRegStr(NULL, "Format", format, "") || !format[0])
  414.     {
  415.         bNoClock = TRUE;
  416.     }
  417.     
  418.     bHour12 = GetMyRegLong(NULL, "Hour12", 0);
  419.     bHourZero = GetMyRegLong(NULL, "HourZero", 0);
  420.     
  421.     bStartMenuClock = FALSE;
  422.     if(GetMyRegLong(NULL, "StartButtonHide", FALSE))
  423.         bStartMenuClock = 
  424.             GetMyRegLong(NULL, "StartMenuClock", FALSE);
  425.     
  426.     if(GetMyRegStr("Tooltip", "Tooltip", s, "") > 0)
  427.         lstrcpyn(tooltip, s, 80);
  428.     else tooltip[0] = 0;
  429.     
  430.     InitFormat();  // cf. format.c
  431. }
  432.  
  433. /*------------------------------------------------
  434.  右クリック時のポップアップメニューの作成
  435. --------------------------------------------------*/
  436. HMENU CreateClockMenu(void)
  437. {
  438.     HMENU hm;
  439.     char entry[10];
  440.     char s[11][80];
  441.     int i;
  442.     
  443.     hm = CreatePopupMenu();
  444.     
  445.     for(i = 0; i < 11; i++)
  446.     {
  447.         wsprintf(entry, "%02d", i);
  448.         GetMyRegStr("DLL", entry, s[i], "");
  449.     }
  450.     
  451.     AppendMenu(hm, MF_STRING, 408, s[0]);
  452.     AppendMenu(hm, MF_STRING, 403, s[1]);
  453.     AppendMenu(hm, MF_STRING, 404, s[2]);
  454.     AppendMenu(hm, MF_STRING, 405, s[3]);
  455.     AppendMenu(hm, MF_SEPARATOR, 0, 0);
  456.     AppendMenu(hm, MF_STRING, 415, s[4]);
  457.     AppendMenu(hm, MF_SEPARATOR, 0, 0);
  458.     if(!(GetVersion() & 0x80000000))
  459.     {
  460.         AppendMenu(hm, MF_STRING, 420, s[5]);
  461.         AppendMenu(hm, MF_SEPARATOR, 0, 0);
  462.     }
  463.     AppendMenu(hm, MF_STRING, 413, s[6]);
  464.     AppendMenu(hm, MF_SEPARATOR, 0, 0);
  465.     AppendMenu(hm, MF_STRING, 103, s[7]);
  466.     AppendTimerMenu(hm);
  467.     AppendMenu(hm, MF_SEPARATOR, 0, 0);
  468.     AppendMenu(hm, MF_STRING, 100, s[8]);
  469.     AppendMenu(hm, MF_STRING, 101, s[9]);
  470.     if(hhook)
  471.         AppendMenu(hm, MF_STRING, 102, s[10]);
  472.     SetMenuDefaultItem(hm, 408, FALSE);
  473.     return hm;
  474. }
  475.  
  476. /*------------------------------------------------
  477.  ツールチップウィンドウの作成
  478. --------------------------------------------------*/
  479. void CreateTip(HWND hwnd)
  480. {
  481.     TOOLINFO ti;
  482.     
  483.     hwndTip = CreateWindow(TOOLTIPS_CLASS, (LPSTR)NULL,
  484.         TTS_ALWAYSTIP,
  485.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  486.         NULL, NULL, hmod, NULL); 
  487.     if(!hwndTip) return;
  488.  
  489.     ti.cbSize = sizeof(TOOLINFO); 
  490.     ti.uFlags = 0;
  491.     ti.hwnd = hwnd;
  492.     ti.hinst = NULL;
  493.     ti.uId = 1;
  494.     ti.lpszText = LPSTR_TEXTCALLBACK;
  495.     ti.rect.left = 0;
  496.     ti.rect.top = 0;
  497.     ti.rect.right = 480; 
  498.     ti.rect.bottom = 480;
  499.     
  500.     SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO)&ti);
  501.     SendMessage(hwndTip, TTM_ACTIVATE, TRUE, 0);
  502. }
  503.  
  504. /*------------------------------------------------
  505.  描画用メモリDCの作成
  506. --------------------------------------------------*/
  507. void CreateClockDC(HWND hwnd)
  508. {
  509.     RECT rc;
  510.     COLORREF col;
  511.     HDC hdc;
  512.     
  513.     if(hdcClock) DeleteDC(hdcClock); hdcClock = NULL;
  514.     if(hbmpClock) DeleteObject(hbmpClock); hbmpClock = NULL;
  515.     
  516.     if(bNoClock) return;
  517.  
  518.     GetClientRect(hwnd, &rc);
  519.     
  520.     hdc = GetDC(NULL);
  521.     
  522.     hdcClock = CreateCompatibleDC(hdc);
  523.     if(!hdcClock) return;
  524.     hbmpClock = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
  525.     if(!hbmpClock) return;
  526.     SelectObject(hdcClock, hbmpClock);
  527.     
  528.     SelectObject(hdcClock, hFon);
  529.     SetBkMode(hdcClock, TRANSPARENT);
  530.     SetTextAlign(hdcClock, TA_CENTER|TA_TOP);
  531.     col = colfore;
  532.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  533.     SetTextColor(hdcClock, col);
  534.     
  535.     ReleaseDC(NULL, hdc);
  536. }
  537.  
  538. /*------------------------------------------------
  539.  WM_TIMER の処理
  540. --------------------------------------------------*/
  541. void OnTimer(HWND hwnd)
  542. {
  543.     SYSTEMTIME t;
  544.     HDC hdc;
  545.     
  546.     GetLocalTime(&t);
  547.     if(bNoClock) hdc = NULL;
  548.     else if(!IsDispSecond(format) && // 秒表示なしのとき
  549.         nBlink == 0 &&
  550.         hourLast == (int)t.wHour && minuteLast == (int)t.wMinute)
  551.          hdc = NULL;
  552.     else hdc = GetDC(hwnd);
  553.     
  554.     // TClockウィンドウにアラーム処理させる
  555.     if(hourLast != (int)t.wHour || minuteLast != (int)t.wMinute)
  556.         PostMessage(hwndTClockMain, WM_USER+4,
  557.             t.wMinute, MAKELONG(t.wHour, t.wDay));
  558.     
  559.     hourLast = t.wHour;
  560.     minuteLast = t.wMinute;
  561.     
  562.     if(nBlink >= 3 && t.wMinute == 1) nBlink = 0;
  563.     
  564.     if(hdc)
  565.     {
  566.         DrawClockSub(hwnd, hdc, &t); //描画
  567.         ReleaseDC(hwnd, hdc);
  568.     }
  569.     
  570.     if(nBlink)
  571.     {
  572.         if(nBlink % 2) nBlink++;
  573.         else nBlink--;
  574.     }
  575.     
  576.     DoTimer(t.wMinute, t.wSecond); // タイマー
  577. }
  578.  
  579. /*------------------------------------------------
  580.  時計の描画
  581. --------------------------------------------------*/
  582. void DrawClock(HWND hwnd, HDC hdc)
  583. {
  584.     SYSTEMTIME t;
  585.     GetLocalTime(&t);
  586.     DrawClockSub(hwnd, hdc, &t);
  587. }
  588. void DrawClockSub(HWND hwnd, HDC hdc, SYSTEMTIME* pt)
  589. {
  590.     COLORREF col;
  591.     HBRUSH hbr;
  592.     RECT rc;
  593.     TEXTMETRIC tm;
  594.     int hf, y;
  595.     char s[1024], *p, *sp;
  596.     
  597.     if(!hdcClock) CreateClockDC(hwnd);
  598.     
  599.     if(!hdcClock || !hbmpClock) return;
  600.     
  601.     MakeFormat(s, pt, format);
  602.     
  603.     GetClientRect(hwnd, &rc);
  604.     GetTextMetrics(hdcClock, &tm);
  605.     
  606.     if(nBlink == 0 || (nBlink % 2)) col = colfore;
  607.     else col = colback;
  608.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  609.     SetTextColor(hdcClock, col);
  610.     
  611.     if(nBlink == 0 || (nBlink % 2)) col = colback;
  612.     else col = colfore;
  613.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  614.     hbr = CreateSolidBrush(col);
  615.     FillRect(hdcClock, &rc, hbr);
  616.     DeleteObject(hbr);
  617.     
  618.     hf = tm.tmHeight - tm.tmInternalLeading;
  619.     p = s;
  620.     y = hf / 4 - tm.tmInternalLeading / 2;
  621.     while(*p)
  622.     {
  623.         sp = p;
  624.         while(*p && *p != 0x0d) p++;
  625.         if(*p == 0x0d) { *p = 0; p += 2; }
  626.         if(*p == 0 && sp == s)
  627.             y = (rc.bottom - tm.tmHeight) / 2  - tm.tmInternalLeading / 4;
  628.         TextOut(hdcClock, rc.right/2, y + dvpos, sp, strlen(sp));
  629.         y += hf; if(*p) y += 2;
  630.     }
  631.     BitBlt(hdc, 0, 0, rc.right, rc.bottom, hdcClock, 0, 0, SRCCOPY);
  632. }
  633.  
  634. /*------------------------------------------------
  635.  時計に必要なサイズを返す
  636.  戻り値:上位WORD 高さ 下位WORD 幅
  637. --------------------------------------------------*/
  638. LRESULT OnCalcRect(HWND hwnd)
  639. {
  640.     SYSTEMTIME t;
  641.     LRESULT w, h;
  642.     HDC hdc;
  643.     TEXTMETRIC tm;
  644.     char s[1024], *p, *sp;
  645.     SIZE sz;
  646.     int hf;
  647.  
  648.     if(!IsWindowVisible(hwnd)) return 0;
  649.     
  650.     hdc = GetDC(hwnd);
  651.     
  652.     if(hFon) SelectObject(hdc, hFon);
  653.     GetTextMetrics(hdc, &tm);
  654.     
  655.     t.wYear = 1996; t.wMonth = 12; t.wDay = 31;
  656.     t.wDayOfWeek = 1; t.wHour = 11; t.wMinute = 30;
  657.     t.wSecond = 30; t.wMilliseconds = 0;
  658.     MakeFormat(s, &t, format);
  659.     
  660.     p = s; w = 0; h = 0;
  661.     hf = tm.tmHeight - tm.tmInternalLeading;
  662.     while(*p)
  663.     {
  664.         sp = p;
  665.         while(*p && *p != 0x0d) p++;
  666.         if(*p == 0x0d) { *p = 0; p += 2; }
  667.         GetTextExtentPoint32(hdc, sp, strlen(sp), &sz);
  668.         if(w < sz.cx) w = sz.cx;
  669.         h += hf; if(*p) h += 2;
  670.     }
  671.     w += tm.tmAveCharWidth * 2;
  672.     h += hf / 2 + dheight;
  673.     
  674.     ReleaseDC(hwnd, hdc);
  675.     
  676.     return (h << 16) + w;
  677. }
  678.  
  679. /*------------------------------------------------
  680.  ツールチップの表示
  681. --------------------------------------------------*/
  682. void OnTooltipNeedText(UINT code, LPARAM lParam)
  683. {
  684.     char s[80];
  685.     
  686.     if(tooltip[0])
  687.         strcpy(s, tooltip);
  688.     else
  689.     {
  690.         strcpy(s, "TClock ");
  691.         GetDateFormat(LOCALE_USER_DEFAULT,
  692.             DATE_LONGDATE, NULL, NULL, s + 7, 80 - 7);
  693.     }
  694.     if(code == TTN_NEEDTEXT)
  695.         strcpy(((LPTOOLTIPTEXT)lParam)->szText, s);
  696.     else
  697.         MultiByteToWideChar(CP_ACP, 0, s, -1,
  698.             ((LPTOOLTIPTEXTW)lParam)->szText, 80);
  699.     SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
  700.         SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
  701. }
  702.